<?php
/**
* Copyright 2010 Dave Keen
* http://www.actionscriptdeveloper.co.uk
*
* This file is part of Flextrine.
*
* Flextrine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* and the Lesser GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Flextrine;

include "Zend/Amf/Server.php";
include "Flextrine/Amf/Response/Http.php";
include "Flextrine/Amf/Request/Http.php";

use Doctrine\ORM\EntityManager,
	Doctrine\ORM\Configuration,
	Doctrine\Common\Cache\ApcCache,
	Doctrine\Common\Annotations\AnnotationReader,
	Doctrine\ORM\Mapping\Driver\AnnotationDriver;

/**
* The Config object retrieves settings from config.php, sets them as static properties, creates and configures the EntityManager and configures AMF
* class mapping.  It is acceptable to inject an EntityManager into Config before calling init() in which case the default EntityManager is not created.
*/
class Config {

	public static $em = null;
	public static $server = null;
	public static $connectionOptions = null;
	public static $flextrineIncludePath = null;
	public static $flextrineManagerEnabled = false;
	public static $productionMode = false;
	public static $entityDir = null;
	public static $proxyDir = null;
	public static $serviceDir = null;
	
	public static function init() {
		// Create the EntityManager if it doesn't exist
		if (!self::$em instanceof EntityManager)
			self::setupEntityManager();
		
		// Create the Zend_Amf_Server (this uses custom request and responders so shouldn't usually be injected)
		if (!self::$server instanceof Zend_Amf_Server)
			self::setupZendAmfServer();
		
	}
	
	private static function setupEntityManager() {
		if (is_null(self::$connectionOptions))
			throw new \Exception("The connectionOptions configuration setting has not been defined in config.php or injected into Config.");
		
		if (is_null(self::$entityDir))
			throw new \Exception("The entityDir configuration setting has not been defined in config.php or injected into Config.");
		
		if (is_null(self::$proxyDir))
			throw new \Exception("The proxyDir configuration setting has not been defined in config.php or injected into Config.");
		
		// Configure and construct the EntityManager
		$config = new Configuration();
		$cache = new ApcCache();
		
		//$config->setMetadataCacheImpl($cache);
		//$config->setQueryCacheImpl($cache);
		
		$config->setProxyDir(self::$proxyDir);
		$config->setProxyNamespace("Proxies");
		$config->setAutoGenerateProxyClasses(true);
		
		$reader = new AnnotationReader();
		$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
		$driverImpl = new AnnotationDriver($reader, array(self::$entityDir));
		$config->setMetadataDriverImpl($driverImpl);
		
		// Create EntityManager and put it into Config
		self::$em = EntityManager::create(Config::$connectionOptions, $config);
	}
	
	private static function setupZendAmfServer() {
		self::$server = new \Zend_Amf_Server();
		self::$server->addDirectory(self::$serviceDir);
		self::$server->setProduction(self::$productionMode);
		
		self::$server->setClassMap('org.davekeen.flextrine.orm.PersistentCollection', '\Doctrine\Common\Collections\ArrayCollection');

		$proxyNamespace = self::$em->getConfiguration()->getProxyNamespace();
		foreach (self::$em->getMetadataFactory()->getAllMetadata() as $metadata) {
			$phpClassName = $metadata->name;
			$as3ClassName = str_replace("\\", ".", $metadata->name);
			
			self::$server->setClassMap($phpClassName, $as3ClassName);
			self::$server->setClassMap($as3ClassName, $proxyNamespace."\\".str_replace("\\", "", $metadata->name)."Proxy");
		}

		self::$server->setResponse(new \Flextrine_Amf_Response_Http());
		self::$server->setRequest(new \Flextrine_Amf_Request_Http());
	}
	
}